package ee.ut.veebirakendus.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.json.JSONObject;

import ee.ut.veebirakendus.engine.GameEngine;

/**
 * Servlet implementation class PokerServlet
 */
public class PokerServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private Logger log;
	private volatile Map<String, GameEngine> sessions;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public PokerServlet() {
		super();
	}

	@Override
	public void init() throws ServletException {
		super.init();
		log = Logger.getLogger(getServletName());
		log.info("PokerServlet initialized");
		sessions = new ConcurrentHashMap<String, GameEngine>();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/plain");
		JSONObject jsonReq = parseRequest(request.getReader());
		log.debug("Message received: " + jsonReq);
		GameEngine engine;
		if (jsonReq.has("sessionId")) {
			log.debug("Session exists, id: " + jsonReq.getString("sessionId"));
			String sessionId = jsonReq.getString("sessionId");
			if (sessions.containsKey(sessionId)) {
				engine = sessions.get(sessionId);
				engine.doAction(jsonReq);
				engine.sendResponse(response);
			} else {
				String message = "Session with id " + sessionId
						+ " does not exist";
				try {
					throw new NoSuchSessionException(message);
				} catch (NoSuchSessionException e) {
					log.error(message, e);
					e.printStackTrace();
				}
			}
		} else {
			if (jsonReq.getString("action").equalsIgnoreCase("gamestart")) {
				String[] randomId = UUID.randomUUID().toString().split("-");
				String sessionId = randomId[randomId.length - 1];
				log.info("New session started, id: " + sessionId);
				engine = new GameEngine(getServletName(), sessionId);
				sessions.put(sessionId, engine);
				engine.doAction(jsonReq);
				engine.sendResponse(response);
			} else {
				String message = "No session id provided in this stage";
				try {
					throw new NoSessionProvidedException(message);
				} catch (NoSessionProvidedException e) {
					log.error(message, e);
					e.printStackTrace();
				}
			}
		}
	}

	private JSONObject parseRequest(BufferedReader reader) {
		String line;
		StringBuilder stringBuilder = new StringBuilder();
		JSONObject request = new JSONObject();
		try {
			while ((line = reader.readLine()) != null) {
				stringBuilder.append(line);
				log.debug("Reader line: " + line);
			}
			String[] pairs = stringBuilder.toString().split("&");
			for (String keyValuePair : pairs) {
				if (keyValuePair.contains("=")) {
					String[] pair = keyValuePair.split("=");
					request.put(pair[0], pair[1]);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return request;
	}

	private class NoSuchSessionException extends Exception {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public NoSuchSessionException(String message) {
			super(message);
		}
	}

	private class NoSessionProvidedException extends Exception {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public NoSessionProvidedException(String message) {
			super(message);
		}
	}
}
